package Json;

import java.io.IOException;
import java.lang.reflect.Type;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

/**
* @author jie
* @version 创建时间：2018年6月13日 下午11:36:57
* 
* 测试失败！！！序列化失败，反序列化成功
* 
* TypeAdapter 是一个泛型抽象类，用于接管某种类型的序列化和反序列化过程，
* 包含两个抽象方法，分别用于自定义序列化和反序列化过程
* 
* public abstract void write(JsonWriter var1, T var2) throws IOException;
* 
* public abstract T read(JsonReader var1) throws IOException;
* 
*  定义 TypeAdapter 的子类 UserTypeAdapter 来接管 User 类的序列化和反序列化过程。
 * 这里设定当 User 
 * 类序列化时 Json 中的Key值都是大写字母开头，
 * 反序列化时支持“name”和“Name”两种不同的 Json 风格
 * 
 * 只接管序列化
 *     其实 Gson 还提供了只接管序列化过程的接口，即 JsonSerializer。
 * 反序列化
 *     相对应的，JsonDeserializer 接口提供了反序列化的接口
 *     
 * 简单的注册方法
 *		使用 TypeAdapter 、JsonSerializer 和 JsonDeserializer 时，
 *		总需要调用 registerTypeAdapter 方法进行注册，那有没有更
 *
 *		@JsonAdapter 用于进行简单的声明。类似于这样，
 *	           声明了 User 类的序列化或反序列化操作由 UserTypeAdapter 完成，
 *		注解的优先级高于 registerTypeAdapter 方法。eg:
 *				
 *		@JsonAdapter(UserTypeAdapter.class)
		public class User {

		}
 *		
 *
*/
public class TypeAdapterTest {
	public static void main(String[] args) {
		
		
		//TypeAdapter 序列化 和 反序列化
//        serializerAndDeserializer();
        
        
        //只接管序列化过程的接口，即 JsonSerializer
//        justJsonSerializer();
        
        //接口提供了反序列化的接口
        justJsonDeserializer();
    }


	/**
	 * TypeAdapter 序列化 和 反序列化
	 */
	private static void serializerAndDeserializer() {
		Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new UserTypeAdapter()).create();
        User5 user = new User5("leavesC", 24, true);
        System.out.println();
        System.out.println(gson.toJson(user));

        String json = "{\"Name\":\"leavesC\",\"age\":24,\"sex\":true}";
        user = gson.fromJson(json, User5.class);
        System.out.println();
        System.out.println(user);
	}

	/**
	 * 只接管序列化过程的接口，即 JsonSerializer
	 */
	private static void justJsonSerializer() {
	    Gson gson = new GsonBuilder().registerTypeAdapter(User5.class, new JsonSerializer<User5>() {
            @Override
            public JsonElement serialize(User5 user, Type type, JsonSerializationContext jsonSerializationContext) {
                JsonObject jsonObject = new JsonObject();
                jsonObject.addProperty("NameHi", user.getName());
                jsonObject.addProperty("Sex", user.isSex());
                jsonObject.addProperty("Age", user.getAge());
                return jsonObject;
            }
        }).create();
        User5 user = new User5("leavesC", 24, true);
        System.out.println();
        System.out.println(gson.toJson(user));
		
	}
	
	/**
	 * 接口提供了反序列化的接口
	 */
	private static void justJsonDeserializer() {
		Gson gson = new GsonBuilder().registerTypeAdapter(User5.class, new JsonDeserializer<User5>() {
            @Override
            public User5 deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
                JsonObject jsonObject = jsonElement.getAsJsonObject();
                String name = null;
                //同时支持 userName 和 name 两种情况
                if (jsonObject.has("userName")) {
                    name = jsonObject.get("userName").getAsString();
                } else if (jsonObject.has("name")) {
                    name = jsonObject.get("name").getAsString();
                }
                int age = jsonObject.get("age").getAsInt();
                boolean sex = jsonObject.get("sex").getAsBoolean();
                return new User5(name, age, sex);
            }
        }).create();
        String json = "{\"userName\":\"leavesC\",\"sex\":true,\"age\":24}";
        User5 user = gson.fromJson(json, User5.class);
        System.out.println();
        System.out.println(user);

        json = "{\"name\":\"leavesC\",\"sex\":true,\"age\":24}";
        user = gson.fromJson(json, User5.class);
        System.out.println();
        System.out.println(user);
		
	}

}

class User5 {

	private String name;

	private int Age;

	private boolean sex;

	public User5() {
	}

	public User5(String name, int age, boolean sex) {
		this.name = name;
		this.Age = age;
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "User5{" + "name='" + name + '\'' + ", age=" + Age + ", sex=" + sex + '}';
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return Age;
	}

	public void setAge(int age) {
		this.Age = age;
	}

	public boolean isSex() {
		return sex;
	}

	public void setSex(boolean sex) {
		this.sex = sex;
	}

}

/**
 * 定义 TypeAdapter 的子类 UserTypeAdapter 来接管 User 类的序列化和反序列化过程。
 * 这里设定当 User 类序列化时 Json 中的Key值都是大写字母开头，反序列化时支持“name”和“Name”两种不同的 Json 风格
 * @author jie
 *
 */
class UserTypeAdapter extends TypeAdapter<User5> {

	@Override
	public void write(JsonWriter jsonWriter, User5 user) throws IOException {
		// 流式序列化成对象开始
		jsonWriter.beginObject();
		// 将Json的Key值都指定为大写字母开头
		jsonWriter.name("Name").value(user.getName());
		jsonWriter.name("Age").value(user.getAge());
		jsonWriter.name("Sex").value(user.isSex());
		// 流式序列化结束
		System.out.println("流式序列化成对象开始  write");
		jsonWriter.endObject();
	}

	@Override
	public User5 read(JsonReader jsonReader) throws IOException {
		User5 user = new User5();
		// 流式反序列化开始
		jsonReader.beginObject();
		while (jsonReader.hasNext()) {
			switch (jsonReader.nextName()) {
			// 首字母大小写均合法
			case "name":
			case "Name":
				user.setName(jsonReader.nextString());
				break;
			case "age":
				user.setAge(jsonReader.nextInt());
				break;
			case "sex":
				user.setSex(jsonReader.nextBoolean());
				break;
			}

		}
		// 流式反序列化结束
		jsonReader.endObject();
		return user;
	}

}